package com.zcc.blog.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zcc.blog.dto.BlogCategoryDto;
import com.zcc.blog.dto.BlogDto;
import com.zcc.blog.dto.BlogDtos;
import com.zcc.blog.dto.BlogMonthDto;
import com.zcc.blog.entity.Blog;
import com.zcc.blog.entity.Category;
import com.zcc.blog.entity.TbCategoryBlog;
import com.zcc.blog.entity.User;
import com.zcc.blog.mapper.BlogMapper;
import com.zcc.blog.mapper.CategoryMapper;
import com.zcc.blog.service.BlogService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zcc.blog.service.TbCategoryBlogService;
import com.zcc.blog.service.UserService;
import com.zcc.blog.untils.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zcc
 * @since 2022-09-05
 */
@Service
public class BlogServiceImpl extends ServiceImpl<BlogMapper, Blog> implements BlogService {

    @Autowired
    BlogMapper blogMapper;
    @Autowired
    CategoryMapper categoryMapper;
    @Autowired
    TbCategoryBlogService tbCategoryBlogService;
    @Autowired
    UserService userService;

    /**
     * 将获得的Blog封装为BlogDto
     * @param records
     * @return
     */
    public List<BlogDto> blogUtil(List<Blog> records){
        List<BlogDto> blogs = new ArrayList<>();
        for (Blog record: records) {
            BlogDto blogDto = new BlogDto();
            blogDto.setBlog(record);
            List<TbCategoryBlog> allByBlogId = tbCategoryBlogService.findAllByBlogId(record.getId());
            List<Category> categories = new ArrayList<>();
            for (TbCategoryBlog t: allByBlogId) {
                Category category = categoryMapper.selectById(t.getCategoryId());
                categories.add(category);
            }
            blogDto.setCategories(categories);
            Long userId = record.getUserId();
            User user = userService.getUserById(userId);
            blogDto.setAuthor(user.getUsername());
            blogs.add(blogDto);
        }
        return blogs;
    }

    @Override
    public Result findBlogs(Integer currentPage, Integer size, Long id, Integer status) {
        Page page = new Page(currentPage, size);
        QueryWrapper<Blog> eq = new QueryWrapper<Blog>().eq("user_id", id).eq("status", status);
        IPage pageData = this.page(page, eq);
        List<Blog> records = pageData.getRecords();
        List<BlogDto> blogs = blogUtil(records);
        int count = this.count(eq);
        BlogDtos blogDtos = new BlogDtos();
        blogDtos.setBlogDtos(blogs);
        blogDtos.setTotal(count);
        return Result.success(blogDtos);
    }

    @Override
    public Result searchBlogs(String title, String description, String content, Integer currentPage, Integer size, Long id, Integer status) {
        Page page = new Page(currentPage, size);
        QueryWrapper<Blog> eq = new QueryWrapper<Blog>().eq("user_id", id).eq("status", status).like("title", title).like("description", description).like("content", content);
        IPage pageData = this.page(page, eq);
        List<Blog> records = pageData.getRecords();
        List<BlogDto> blogs = blogUtil(records);
        int count = this.count(eq);
        BlogDtos blogDtos = new BlogDtos();
        blogDtos.setBlogDtos(blogs);
        blogDtos.setTotal(count);
        return Result.success(blogDtos);
    }

    @Override
    public Result addBlog(BlogCategoryDto blogCategoryDto) {
        Blog blog = blogCategoryDto.getBlog();
        String title = blog.getTitle();
        HashMap<String, Object> map = new HashMap<>();
        map.put("title", title);
        Collection<Blog> blogs = this.listByMap(map);
        if (blogs.size() == 0) {
            Blog temp = new Blog();
            temp.setStatus(0);
            temp.setRecommend(0);
            temp.setCreated(LocalDateTime.now());
            BeanUtil.copyProperties(blog,temp,"id","created","status", "recommend");
            boolean save = this.save(temp);
            if (save) {
                // 新增成功后返回的新增博客的id
                Long blogId = temp.getId();
                List<Long> categoryIds = blogCategoryDto.getCategoryIds();
                for (Long categoryId: categoryIds) {
                    TbCategoryBlog tbCategoryBlog = new TbCategoryBlog();
                    tbCategoryBlog.setBlogId(blogId);
                    tbCategoryBlog.setCategoryId(categoryId);
                    tbCategoryBlog.setStatus(0);
                    tbCategoryBlogService.save(tbCategoryBlog);
                }
                return Result.success(null);
            } else {
                return Result.fail("添加文章失败");
            }
        }
        return Result.fail("该标题已经存在，请修改");
    }

    /**
     * 首先判断修改博客的时候标题是否修改，
     * 若是没有修改就可以直接修改本篇博客，无须考虑博客是否重名的情况，
     * 否者当修改的博客的标题与其他博客标题相同的时候就修改失敗
     * @param blogCategoryDto
     * @return
     */
    @Override
    public Result updateBlog(BlogCategoryDto blogCategoryDto) {
        Blog blog = blogCategoryDto.getBlog();
        String title = blog.getTitle();
        Blog byId = this.getById(blog.getId());
        boolean currentBlog = byId.getTitle().equals(title);
        if (currentBlog) {
            Blog temp = new Blog();
            temp.setStatus(0);
            temp.setCreated(LocalDateTime.now());
            BeanUtil.copyProperties(blog,temp,"created","status");
            boolean update = this.updateById(temp);
            if (update) {
                Long blogId = temp.getId();
                // 先将该博客对应的分类删除，然后再重新添加博客对应的分类
                List<TbCategoryBlog> blog_id = tbCategoryBlogService.list(new QueryWrapper<TbCategoryBlog>().eq("blog_id", blogId));
                if (blog_id.size() != 0) {
                    for (TbCategoryBlog tbCategoryBlog : blog_id) {
                        tbCategoryBlogService.removeById(tbCategoryBlog.getId());
                    }
                }
                List<Long> categoryIds = blogCategoryDto.getCategoryIds();
                for (Long categoryId: categoryIds) {
                    TbCategoryBlog tbCategoryBlog = new TbCategoryBlog();
                    tbCategoryBlog.setBlogId(blogId);
                    tbCategoryBlog.setCategoryId(categoryId);
                    tbCategoryBlog.setStatus(0);
                    tbCategoryBlogService.save(tbCategoryBlog);
                }
                return Result.success(null);
            } else {
                return Result.fail("添加文章失败");
            }
        }
        HashMap<String, Object> map = new HashMap<>();
        map.put("title", title);
        Collection<Blog> blogs = this.listByMap(map);
        if (blogs.size() == 0) {
            Blog temp = new Blog();
            temp.setStatus(0);
            temp.setCreated(LocalDateTime.now());
            BeanUtil.copyProperties(blog,temp,"created","status");
            boolean update = this.updateById(temp);
            if (update) {
                Long blogId = temp.getId();
                // 先将该博客对应的分类删除，然后再重新添加博客对应的分类
                List<TbCategoryBlog> blog_id = tbCategoryBlogService.list(new QueryWrapper<TbCategoryBlog>().eq("blog_id", blogId));
                if (blog_id.size() != 0) {
                    for (TbCategoryBlog tbCategoryBlog : blog_id) {
                        tbCategoryBlogService.removeById(tbCategoryBlog.getId());
                    }
                }
                List<Long> categoryIds = blogCategoryDto.getCategoryIds();
                for (Long categoryId: categoryIds) {
                    TbCategoryBlog tbCategoryBlog = new TbCategoryBlog();
                    tbCategoryBlog.setBlogId(blogId);
                    tbCategoryBlog.setCategoryId(categoryId);
                    tbCategoryBlog.setStatus(0);
                    tbCategoryBlogService.save(tbCategoryBlog);
                }
                return Result.success(null);
            } else {
                return Result.fail("添加文章失败");
            }
        }
        return Result.fail("该标题已经存在，请修改");
    }

    @Override
    public Result sortOrder(Integer currentPage, Integer size, Long id) {
        Page page = new Page(currentPage, size);
        QueryWrapper<Blog> eq = new QueryWrapper<Blog>().eq("user_id", id).eq("status", 0).orderByDesc("created");
        IPage pageData = this.page(page, eq);
        List<Blog> records = pageData.getRecords();
        List<BlogDto> blogs = blogUtil(records);
        int count = this.count(eq);
        BlogDtos blogDtos = new BlogDtos();
        blogDtos.setBlogDtos(blogs);
        blogDtos.setTotal(count);
        return Result.success(blogDtos);
    }

    @Override
    public Result sortReversed(Integer currentPage, Integer size, Long id) {
        Page page = new Page(currentPage, size);
        QueryWrapper<Blog> eq = new QueryWrapper<Blog>().eq("user_id", id).eq("status", 0).orderByAsc("created");
        IPage pageData = this.page(page, eq);
        List<Blog> records = pageData.getRecords();
        List<BlogDto> blogs = blogUtil(records);
        int count = this.count(eq);
        BlogDtos blogDtos = new BlogDtos();
        blogDtos.setBlogDtos(blogs);
        blogDtos.setTotal(count);
        return Result.success(blogDtos);
    }

    @Override
    public Result deleteBlog(Long id) {
        boolean b = blogMapper.changeStatus(1, id);
        if (b) {
            // 删除该博客下的博客分类中间表
            List<TbCategoryBlog> tbCategoryBlogs = tbCategoryBlogService.list(new QueryWrapper<TbCategoryBlog>().eq("blog_id", id));
            if (tbCategoryBlogs.size() != 0) {
                for (TbCategoryBlog tb: tbCategoryBlogs) {
                    tbCategoryBlogService.deleteTbCategoryBlog(tb.getId());
                }
            }
            return Result.success(null);
        }
        return Result.fail("删除失败");
    }

    @Override
    public Result recoverBlog(Long id) {
        boolean b = blogMapper.changeStatus(0, id);
        if (b) {
            // 恢复该博客下的博客分类中间表
            List<TbCategoryBlog> tbCategoryBlogs = tbCategoryBlogService.list(new QueryWrapper<TbCategoryBlog>().eq("blog_id", id));
            if (tbCategoryBlogs.size() != 0) {
                for (TbCategoryBlog tb: tbCategoryBlogs) {
                    tbCategoryBlogService.recoverTbCategoryBlog(tb.getId());
                }
            }
            return Result.success(null);
        }
        return Result.fail("删除失败");
    }

    @Override
    public Result openRecommend(Long id) {
        boolean b = blogMapper.changeRecommend(1, id);
        if (b) {
            return Result.success(null);
        }
        return Result.fail("开启自我推荐失败");
    }

    @Override
    public Result closeRecommend(Long id) {
        boolean b = blogMapper.changeRecommend(0, id);
        if (b) {
            return Result.success(null);
        }
        return Result.fail("关闭自我推荐失败");
    }

    @Override
    public Result findRecommendBlogs(Integer currentPage, Integer size) {
        Page page = new Page(currentPage, size);
        QueryWrapper<Blog> eq = new QueryWrapper<Blog>().eq("status", 0).eq("recommend", 1);
        IPage pageData = this.page(page, eq);
        List<Blog> records = pageData.getRecords();
        List<BlogDto> blogs = blogUtil(records);
        int count = this.count(eq);
        BlogDtos blogDtos = new BlogDtos();
        blogDtos.setBlogDtos(blogs);
        blogDtos.setTotal(count);
        return Result.success(blogDtos);
    }

    @Override
    public Result countBlogsByMonth(Long id) {
        List<BlogMonthDto> blogMonthDtos = blogMapper.countBlogsByMonth(id);
        Integer[] data = new Integer[12];
        Arrays.fill(data, 0);
        System.out.println(data[10]);
        for (BlogMonthDto b: blogMonthDtos) {
            Integer months = b.getMonths();
            data[months-1] = b.getTotal();
        }
        List<Integer> total = Arrays.asList(data);
        return Result.success(total);
    }

    @Override
    public Result countBlogs(Long id) {
        QueryWrapper<Blog> eq = new QueryWrapper<Blog>().eq("user_id", id).eq("status", 0);
        int count = this.count(eq);
        return Result.success(count);
    }

    @Override
    public Result findBlogById(Long id) {
        QueryWrapper<Blog> eq = new QueryWrapper<Blog>().eq("id", id).eq("status", 0);
        List<Blog> list = this.list(eq);
        List<BlogDto> blogDtos = blogUtil(list);
        System.out.println(list);
        return Result.success(blogDtos.get(0));
    }

}
